<template>
  <div :class="['components-chart-box', chartClass, props.bordered && 'bordered', props.theme]">
    <h4 v-if="props.title" class="chart-title" ref="titleRef">{{ props.title }}

      <slot name="tip"></slot>
    </h4>
    <a-button @click="toggleChartType" style="position: absolute; top: 30px; left: 15px; z-index: 999;">{{ chartType === 'line' ? '切换到柱状图' : '切换到曲线图' }}</a-button>
    <a-select :getPopupContainer="(triggerNode) => { return triggerNode.parentNode || document.body }"
      v-if="isFirstInitial && !showLegend" :maxTagCount="1" mode="multiple" :class="['chart-title-right', 'min-w-48']"
      :options="selectOptions" :disabled="selectOptions.length < 2" :value="selectLegendValue" @change="handleChange" allowClear>
    </a-select>
    <div :class="['chart-container']" v-loading="loading" ref="chartRef" :style="{ height, width, marginTop: '10px' }">
    </div>
  </div>
</template>

<script lang="ts" setup>
import { onMounted, PropType, Ref, ref, watch, onUnmounted, watchEffect, nextTick } from 'vue'

import { useECharts } from '@/hooks/web/useECharts'
import { EChartsOption } from 'echarts'
import { getCssVariableValue, getRandomColor, lightenColor, hexToRgb } from '../common'
import { lineColorArr } from './data'
import '../style.scss'
import { XAXisOption } from 'echarts/types/dist/shared'
import { cloneDeep } from 'lodash-es'

const props = defineProps({
  width: {
    type: String as PropType<string>,
    default: '100%',
  },
  height: {
    type: String as PropType<string>,
    default: '100%',
  },
  loading: {
    type: Boolean,
    default: false,
  },
  bordered: {
    type: Boolean,
    default: true,
  },
  title: {
    type: String as PropType<string>,
    default: '',
  },
  chartData: {
    type: Object as PropType<object>,
  },
  chartClass: {
    type: Object as PropType<string>,
  },
  unit: {
    type: String as PropType<string>,
    default: '',
  },
  xyDataFieldsName: {
    type: Object as PropType<{
      xDataField: string
      yDataField: string,
      lineYData: string
    }>,
    default: () => ({
      xDataField: 'xaxisList',
      yDataField: 'yaxisList',
      lineYData: 'codeyAxisList',
    }),
  },
  theme: {
    type: String,
    default: 'white'
  },
  showLegend: {
    type: Boolean,
    default: false
  },
  showNumber: {
    type: Number
  },
  customOptions: {
    type: Function
  },
  customSelect: {
    type: Function
  }
})

let resizeObserver: ResizeObserver | null = null
const isFirstInitial = ref(false)
const selectOptions = ref([])
const selectLegendValue = ref([])
const chartRef = ref<HTMLDivElement | null>(null)
const titleRef = ref<HTMLDivElement | null>(null)
const { setOptions, echarts, resize, getInstance } = useECharts(chartRef as Ref<HTMLDivElement>)
const gridLineColor = props.theme === 'dark' ? 'rgba(255,255,255,0.12)' : getCssVariableValue('--chart-grid-line-color')
const textColor = props.theme === 'dark' ? 'rgba(255,255,255,0.70)' : getCssVariableValue('--chart-text-color')

// 存储系列名称到颜色的映射
const seriesColorMap = ref({})

const gridTop = 18 + 12 + 12 + 25
const options: EChartsOption = {
  legend: {
    show: props.showLegend,
    right: 16,
    padding: 0,
    top: 15,
    textStyle: {
      color: textColor,
    },
    icon: 'rect',
    itemWidth: 11,
    itemHeight: 2,
  },
  grid: {
    left: '18px',
    right: '24px',
    bottom: '12px',
    top: gridTop,
    containLabel: true,
  },
  tooltip: {
    trigger: 'axis',
    axisPointer: {
      type: 'cross',
      snap: true,
      label: {
        show: true,
        backgroundColor: '#333',
      },
    },
    confine: true,
    appendToBody: true,
    className: ['echarts-line-tooltip', props.theme].join(' '),
    backgroundColor: props.theme === 'dark' ? 'rgba(50,68,121,0.50);' : '#fff',
    formatter: function (params) {
      if (!params || params.length === 0) return '';
      
      const title = params[0].name || '';
      
      // 生成带颜色标识的系列内容
      const seriesContent = params.map(param => {
        // 从映射表中获取颜色
        const color = seriesColorMap.value[param.seriesName] || '#666';
        
        return `
          <div style="display: flex; align-items: center; margin-bottom: 4px;">
            <div style="width: 10px; height: 10px; background-color: ${color}; margin-right: 6px; border-radius: 2px;"></div>
            <span>${param.seriesName}: ${param.value}</span>
          </div>
        `;
      }).join('');

      return `<div class="echarts-tooltip-title">${title}</div>${seriesContent}`;
    },
    position: function (pos, params, dom, rect, size) {
      // 鼠标在左侧时 tooltip 显示到右侧，鼠标在右侧时 tooltip 显示到左侧。
      var obj = {top: 50};
      obj[['left', 'right'][+(pos[0] < size.viewSize[0] / 2)]] = 5;
      return obj;
  }
  },
  xAxis: {
    axisLine: {
      lineStyle: {
        color: gridLineColor,
      },
    },
    axisLabel: {
      color: textColor,
    },
  },
  yAxis: {
    nameTextStyle: {
      color: textColor,
      fontSize: '12px',
    },
    splitLine: {
      lineStyle: {
        color: gridLineColor,
      },
    },
    axisLine: {
      lineStyle: {
        color: gridLineColor,
      },
    },
    axisLabel: {
      color: textColor,
    },
  }
}

const chartType = ref('line')

onMounted(() => {
  // setData()

  resizeObserver = new ResizeObserver(() => {
    resize()
  })
  if (chartRef.value) {
    resizeObserver.observe(chartRef.value as HTMLDivElement)
  }
  console.log(getInstance())
})

onUnmounted(() => {
  if (resizeObserver && chartRef.value) {
    resizeObserver.unobserve(chartRef.value as HTMLDivElement)
  }
})


const handleChange = (params: any) => {
  selectLegendValue.value = params
  const originOption = getInstance()?.getOption() as EChartsOption

  if (originOption?.legend) {
    Object.keys(originOption.legend[0].selected).forEach(key => {
      if (selectLegendValue.value.find(item => key.indexOf(item) > -1)) {
        originOption.legend[0].selected[key] = true
      } else {
        originOption.legend[0].selected[key] = false
      }
    })
    setOptions(originOption)
  }
}

const setData = () => {
  const { xDataField, yDataField, lineYData } = props.xyDataFieldsName
  if (!props.chartData || !chartRef.value) return
  let chartData = cloneDeep(props.chartData)
  const chartTitleW = titleRef.value ? titleRef.value.offsetWidth : 0
  const legendWidth = chartRef.value?.clientWidth - chartTitleW - 36
  const xData = chartData[xDataField]
  const yData = chartData[yDataField]
  let lineData = chartData[lineYData] || []
  if (!xData || !yData || !xData.length) return
  let temporaryOptions = yData.concat(lineData).map((item) => ({
    label: item?.name || '',
    value: item?.name || '',
  }))
  if (props.customOptions) {
    console.log(111111111)
    selectOptions.value = props.customOptions(temporaryOptions)
  } else {
    selectOptions.value = temporaryOptions
  }
  if (lineData) {
    if (props.customOptions) {
      selectLegendValue.value = selectOptions.value.map(item => item.value)
    } else {
      selectLegendValue.value = yData.concat(lineData).map(item => item.name)
    }
  } else {
    if (props.customOptions) {
      selectLegendValue.value = selectOptions.value[0].value
    } else {
      selectLegendValue.value = yData[0]?.name || ''
    }
  }

  const showUnit = yData.length && props.unit
  
  // 构建系列名称到颜色的映射
  const colorMap = {}
  const line1List = yData.map((item, index) => {
    let colorArr = lineColorArr?.[index]

    if (!colorArr) {
      const color1 = getRandomColor()
      const color2 = lightenColor(color1)
      colorArr = [color1, color2]
    }
    
    // 保存系列名称和对应的颜色（使用渐变的第一个颜色）
    colorMap[item.name || `series${index}`] = colorArr[0]

    return {
      ...item,
      data: cloneDeep(item.data),
      type: chartType.value,
      smooth: chartType.value === 'line',
      showSymbol: false,
      emphasis: {
        focus: 'series',
        label: {
          show: true,
          formatter: '{a}: {c}',
          backgroundColor: '#fff',
          padding: 12,
          color: '#333',
          shadowColor: '#999',
          shadowBlur: 4,
        }
      },
     
      itemStyle: {
        color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
          { offset: 0, color: colorArr[0] },
          { offset: 1, color: colorArr[1] },
        ]),
      },
      lineStyle: {
        width: 2,
      },
    }
  })
  
  const line2List = lineData.map((item, index) => {
   let colorArr = lineColorArr?.[index+line1List.length]
    if (!colorArr) {
      const color1 = getRandomColor()
      const color2 = lightenColor(color1)
      colorArr = [color1, color2]
    }
    colorMap[item.name || `series${index}`] = colorArr[0]
    return {
      ...item,
      type: 'line',
      smooth: chartType.value === 'line',
      showSymbol: false,
      emphasis: {
        focus: 'series',
        label: {
          show: true,
          formatter: '{a}: {c}',
          backgroundColor: '#fff',
          padding: 12,
          color: '#333',
          shadowColor: '#999',
          shadowBlur: 4,
        }
      },
      yAxisIndex: 1,
      itemStyle: {
        color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
          { offset: 0, color: colorArr[0] },
          { offset: 1, color: colorArr[1] },
        ]),
      },
      width: 2,
    }
  })
  const series = [...line1List, ...line2List]
  // 更新颜色映射
  seriesColorMap.value = colorMap
  let lineDataUnits = new Set()
  lineData.forEach(item => {
    lineDataUnits.add(item.unit)
  })
  let lineDataUnitString = ''
  lineDataUnits.forEach(item => {
    lineDataUnitString += '单位：'+item + '\n'
  })
  let selected = yData.concat(lineData || []).reduce((prev, item, index) => {
    index == 0 ? (prev[item?.name || ''] = true) : (prev[item?.name || ''] = true)
    return prev
  }, {})
  if (props.showNumber) {
    let number = 0
    selectLegendValue.value = []
    Object.keys(selected).forEach((key) => {
      if (number < props.showNumber) {
        selected[key] = true
        number++
        selectLegendValue.value.push(key)
      } else {
        selected[key] = false
      }
      
    })
  }
  let currentOptions = {
    ...options,
    legend: {
      ...options.legend,
      width: legendWidth,
      data: yData.concat(lineData || []).map((item) => item?.name || ''),
      selected: selected,
      type: 'scroll',
      pageTextStyle: {
        color: textColor
      }
    },
    grid: {
      ...options.grid,
      top: showUnit ? gridTop + 14 : gridTop,
    },
    xAxis: {
      ...options.xAxis,
      data: xData,
    } as XAXisOption,
    yAxis: [
      {
        ...options.yAxis,
        name: showUnit && `单位：${props.unit}`,
      },
      {
        ...options.yAxis,
        name: showUnit && lineDataUnitString,
      },
    ],
    series,
    backgroundColor: '#fff'
  }
  setOptions(currentOptions)

}

const toggleChartType = () => {
  chartType.value = chartType.value === 'line' ? 'bar' : 'line'
  setData()
}

watch(
  () => props.chartData,
  (val) => {
    nextTick(() => {
      setData()
    })
  },
  {
    immediate: true,
    deep: true
  },
)

watch(selectOptions, () => {
  selectOptions.value.length && (isFirstInitial.value = true)
})

defineExpose({})

</script>

<style lang="scss" scoped>
.echarts-line-tooltip {
  &.dark {
    border-color: rgb(162 193 255 / 30%) !important;

    .legend-list {
      li {
        color: #fff;
      }
    }
  }

  .legend-list {
    li {
      display: flex;
      align-items: center;
      color: #666;
      font-size: 12px;
      line-height: 24px;

      &:not(:last-child) {
        margin-bottom: 4px;
      }

      .rect {
        display: block;
        width: 11px;
        height: 2px;
        margin-right: 3px;
      }
    }
  }

  .echarts-tooltip-title {
    font-weight: bold;
    padding-bottom: 6px;
    border-bottom: 1px solid #eee;
  }
}
</style>